package org.jeecg.modules.meter.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.RedisKeyConstant;
import org.jeecg.common.util.*;
import org.jeecg.config.Sm4Util;
import org.jeecg.entity.charge.ChargeInvoiceRequest;
import org.jeecg.entity.meter.*;
import org.jeecg.enums.InvoiceTypeEnum;
import org.jeecg.enums.PayModeEnum;
import org.jeecg.enums.PayStatusEnum;
import org.jeecg.enums.common.PayTypeEnum;
import org.jeecg.enums.meter.MeterChargeStatusEnum;
import org.jeecg.enums.meter.MeterChargeTypeEnum;
import org.jeecg.enums.meter.RefundStatusEnum;
import org.jeecg.lock.client.RedissonLockClient;
import org.jeecg.model.charge.reqvo.DayReportReqVo;
import org.jeecg.model.charge.resvo.DayReportRespVo;
import org.jeecg.model.meter.reqvo.MeterDayReportReqVo;
import org.jeecg.model.meter.resvo.MeterDayReportRespVo;
import org.jeecg.modules.meter.entity.MeterPayConfig;
import org.jeecg.modules.meter.entity.MeterRoom;
import org.jeecg.modules.meter.entity.PayAccountConfig;
import org.jeecg.modules.meter.mapper.MeterFeeRuleMapper;
import org.jeecg.modules.meter.mapper.MeterOrderInvoiceMapper;
import org.jeecg.modules.meter.mapper.MeterOrderMapper;
import org.jeecg.modules.meter.mapper.MeterRoomMapper;
import org.jeecg.modules.meter.service.*;
import org.jeecg.modules.system.entity.FFTCreateOrder;
import org.jeecg.modules.system.entity.FFTFeeItem;
import org.jeecg.service.IFeignChargeService;
import org.jeecg.vo.meter.MeterChargeRespVo;
import org.jeecg.vo.meter.MeterSwitchRespVo;
import org.jeecg.vo.pay.FFTPayNotify;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * @Description: 仪器充值订单表
 * @Author: jeecg-boot
 * @Date:   2020-11-27
 * @Version: V1.0
 */
@Service
@Slf4j
public class MeterOrderServiceImpl extends ServiceImpl<MeterOrderMapper, MeterOrder> implements IMeterOrderService {
    private final Queue<String> payQueue = new ConcurrentLinkedQueue<String>();

    @Autowired
    private IMeterService meterService;

    @Autowired
    private MeterOrderMapper meterOrderMapper;

    @Autowired
    private MeterRoomMapper meterRoomMapper;

    @Autowired
    private MeterOrderInvoiceMapper meterOrderInvoiceMapper;

    @Autowired
    private IMeterChargeInfoService meterChargeInfoService;
    @Autowired
    private MeterFeeRuleMapper meterFeeRuleMapper;
    @Autowired
    private RedissonLockClient lockClient;
    @Autowired
    private IMeterFeeRuleService meterFeeRuleService;
    @Autowired
    private IMeterControlSwitchService meterControlSwitchService;
    @Autowired
    private IFeignChargeService feignChargeService;


    @Value("${pay.fftEncryptKey}")
    private String fftEncryptKey; //付费通加密key

    /**
     * 仪表退款 --- 线下
     * @param orderId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<MeterOrder> refundCharge(String orderId) {
        Result<MeterOrder> result = new Result<MeterOrder>();
        if (StringUtils.isBlank(orderId)) throw new RuntimeException("查询参数有误");
        MeterOrder meterOrder = meterOrderMapper.selectById(orderId);
        if (meterOrder == null){
            return Result.error("系统中未查到需要退款的表号！");
        }
        if (meterOrder.getRefundStatus().equals(RefundStatusEnum.REFUND_STATUS_YES.getCode())){
            return Result.error("当前订单已退款，请勿重复操作");
        }
        try {
           //修改订单表状态
            meterOrder.setRefundStatus(RefundStatusEnum.REFUND_STATUS_YES.getCode());
            meterOrder.setRefundTime(new Date());
            meterOrder.setRefundBy(SsoUtil.getLoginUser().getId());
            this.updateById(meterOrder);
            //刷新账号余额 - 根据支付明细记录
            //构造充值明细记录
            MeterFeeRule meterFeeRule = meterFeeRuleService.queryFeeByMeterId(meterOrder.getMeterId());
            Integer roundMode = meterFeeRule.getRoundMode();
            MeterChargeInfo meterCharge = new MeterChargeInfo();
            meterCharge.setId(UUID.randomUUID().toString().replace("-", ""));
            meterCharge.setChargeAmount(new BigDecimal(meterOrder.getPayAmount()).negate().toString());
            meterCharge.setChargeType(MeterChargeTypeEnum.METER_CHARGE_TYPE_REFUND.getCode());
            meterCharge.setChargeTime(new Date());
            meterCharge.setMeterId(meterOrder.getMeterId());
            meterCharge.setChargeStatus(MeterChargeStatusEnum.METER_CHARGE_STATUS_OK.getCode());
            meterCharge.setPaymentStatus(PayStatusEnum.PAY_STATUS_YES.getCode());
            meterCharge.setMeterOrderId(meterOrder.getId());
            meterCharge.setRound(roundMode);
            meterChargeInfoService.save(meterCharge);
            //费用明细表集合
            List<MeterChargeRespVo> meterChargeList = Lists.newArrayList();
            MeterChargeRespVo meterChargeRespVo = new MeterChargeRespVo();
            BeanUtils.copyProperties(meterCharge,meterChargeRespVo);
            meterChargeList.add(meterChargeRespVo);
            List<MeterSwitchRespVo> switchRespVoList = meterChargeInfoService.refreshRemainByPay(meterChargeList, meterOrder.getId(), MeterChargeTypeEnum.METER_CHARGE_TYPE_REFUND.getCode());
            meterOrder.setSwitchRespVoList(switchRespVoList);

            // 红冲发票
            if ((""+meterOrder.getInvoiceStatus()).equals(InvoiceTypeEnum.INVOICE_TYPE_ELE.getCode())){
                List<ChargeInvoiceRequest> list = meterOrderMapper.invoiceRequestListBySn(meterOrder.getSn());
                for (ChargeInvoiceRequest temp : list){
                    feignChargeService.openRed(JSON.toJSONString(temp), temp.getTenantId());
                }
            }
        }catch (RuntimeException re){
            log.error("MeterOrderServiceImpl refundCharge 异常",re);
            throw new RuntimeException(re.getMessage());
        } catch (Exception e){
            log.error("MeterOrderServiceImpl refundCharge 异常",e);
            throw new RuntimeException("退款处理异常,充值失败",e);
        }
        return Result.ok(meterOrder);
    }


    /**
     * 付费通回调
     * @param fftPayNotify
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<MeterOrder> meterPayNotify(FFTPayNotify fftPayNotify) {
        //分布式锁 -- 防止重复回调
        String lockKey = RedisKeyConstant.METER_ORDER_KEY + fftPayNotify.getOrderId();
        boolean getLock = lockClient.tryLock(lockKey,0,120);
        if (!getLock) {
            log.warn("仪表支付回调,订单支付中transNo:{},sn:{}",fftPayNotify.getTransNo(),fftPayNotify.getOrderId());
            return Result.error("订单支付中");
        }
        log.info("仪表支付回调销账接受参数:{}",fftPayNotify);
        MeterOrder meterOrder =  meterOrderMapper.getOrderBySn(fftPayNotify.getOrderId());
        //通知成功
        if (meterOrder == null) {
            log.error("仪表支付回调获取订单信息失败:{}",fftPayNotify.getOrderId());
            return Result.error("获取订单信息失败");//销账失败
        }
        //已支付。直接结束
        if (meterOrder.getPayStatus() == 1) {
            log.warn("仪表支付回调当前订单状态为已支付:{}",fftPayNotify.getOrderId());
            return Result.error("订单状态为已支付");
        }

        payQueue.add(fftPayNotify.getOrderId());
        Meter meter = meterService.getSelfById( meterOrder.getMeterId());
        if (meter == null){
            return Result.error("系统中未查到需要充值的表号！");
        }
        try {
            //1.订单明细表 meter_charge_info
            MeterChargeInfo meterCharge = meterChargeInfoService.getByOrderId(meterOrder.getId());
            List<MeterOrderInvoice> meterOrderInvoiceList = new ArrayList<>();
            if (meterCharge == null){
                //创建明细信息
                meterCharge = new MeterChargeInfo();
                MeterFeeRule meterFeeRule = meterFeeRuleService.queryFeeByMeterId(meterOrder.getMeterId());
                Integer roundMode = meterFeeRule.getRoundMode();
                meterCharge.setId(UUID.randomUUID().toString().replace("-", ""));
                meterCharge.setChargeAmount(meterOrder.getPayAmount());
                meterCharge.setChargeType(MeterChargeTypeEnum.METER_CHARGE_TYPE_PAY.getCode());
                meterCharge.setChargeTime(new Date());
                meterCharge.setMeterId(meterOrder.getMeterId());
                meterCharge.setChargeStatus(MeterChargeStatusEnum.METER_CHARGE_STATUS_ING.getCode());
                meterCharge.setMeterOrderId(meterOrder.getId());
                meterCharge.setRound(roundMode);
                meterCharge.setTenantId(meter.getTenantId());
                meterOrderInvoiceList = getMeterOrderInvoiceList(meterOrder, meter, meterCharge);
                meterCharge.setPaymentStatus(PayStatusEnum.PAY_STATUS_YES.getCode());
                meterChargeInfoService.save(meterCharge);
            }
            if (meterOrderInvoiceList.size() > 0) {
                meterOrderInvoiceMapper.batchInsert(meterOrderInvoiceList);
            }
            List<MeterChargeRespVo> meterChargeList = Lists.newArrayList(); //费用明细表集合
            MeterChargeRespVo meterChargeRespVo = new MeterChargeRespVo();
            BeanUtils.copyProperties(meterCharge,meterChargeRespVo);
            meterChargeList.add(meterChargeRespVo);
            try {
                List<MeterSwitchRespVo> switchRespVoList = meterChargeInfoService.refreshRemainByPay(meterChargeList, meterOrder.getId(), MeterChargeTypeEnum.METER_CHARGE_TYPE_PAY.getCode());
                meterOrder.setSwitchRespVoList(switchRespVoList);
                meterChargeInfoService.updateChargeStatus(meterCharge.getId(),MeterChargeStatusEnum.METER_CHARGE_STATUS_OK.getCode());
            }catch (Exception e){
            }
            meterOrderMapper.updatePayStatus(meterOrder.getId(),fftPayNotify.getPaymentTime(),PayStatusEnum.PAY_STATUS_YES.getCode());
        } catch (Exception e) {
            log.error("仪表支付回调更新订单表异常:{}",e);
            throw new RuntimeException(e);
        } finally {
            payQueue.remove(fftPayNotify.getOrderId());
        }
        return Result.ok(meterOrder);
    }

    @Override
    public List<MeterDayReportRespVo> findGroupList(MeterDayReportReqVo meterDayReportRespVo) {
        return meterOrderMapper.findGroupList(meterDayReportRespVo);
    }

    @Override
    public List<DayReportRespVo> apiFindGroupList(DayReportReqVo dayReportReqVo){
        return meterOrderMapper.apiFindGroupList(dayReportReqVo);
    };



    @Override
    public Result meterBlueInvoice(MeterOrder meterOrder) {
        if (null == meterOrder){
            return Result.error("开票订单异常！");
        }
        if (InvoiceTypeEnum.INVOICE_TYPE_ELE.getCode().equals((meterOrder.getInvoiceStatus() + ""))) {
            // todo 后续配置在表里
            if (ComUtil.isLastDayOfMonth(new Date())){
                log.info("当月最后一天停止开票");
                return Result.error("当月最后一天停止开票!");
            }

            MeterRoom meterRoom = meterRoomMapper.selectByMeterId(meterOrder.getMeterId());
            // 电子发票
            ChargeInvoiceRequest invoiceReqDetail = new ChargeInvoiceRequest();
            invoiceReqDetail.setProjectId(meterOrder.getProjectId());
            invoiceReqDetail.setGmfMc(meterOrder.getInvoiceName());
            invoiceReqDetail.setMoney(Double.valueOf(meterOrder.getPayAmount()));
            invoiceReqDetail.setAddress(meterOrder.getInvoiceAddress());
            invoiceReqDetail.setPayMethod(Integer.valueOf(meterOrder.getPayType()));
            invoiceReqDetail.setPayMode(meterOrder.getPayMode());
            invoiceReqDetail.setCreateTime(new Date());
            // TODO
            invoiceReqDetail.setFeeitemId("5e6f302de10255c7a6424055ddea7acc");
            invoiceReqDetail.setDelFlag("0");
            invoiceReqDetail.setOrderNum(meterOrder.getSn());
            invoiceReqDetail.setTenantId(meterOrder.getTenantId());
            invoiceReqDetail.setRemarks(ComUtil.dateTimeFmt(new Date(), "yyyy-MM-dd") + "\n" + meterRoom.getAddress());
            if (StringUtils.isNotEmpty(meterOrder.getInvoiceEmail())) {
                invoiceReqDetail.setEmail(meterOrder.getInvoiceEmail());
            }
            if (StringUtils.isNotEmpty(meterOrder.getInvoiceMobile())) {
                invoiceReqDetail.setTel(meterOrder.getInvoiceMobile());
            }
            if (StringUtils.isNotEmpty(meterOrder.getInvoiceEin())) {
                invoiceReqDetail.setEin(meterOrder.getInvoiceEin());
            }
            if (StringUtils.isNotEmpty(meterOrder.getInvoiceAccount())) {
                invoiceReqDetail.setAccount(meterOrder.getInvoiceAccount());
            }
            try {
                double maxMoney = 9999;
                // 分多次开金额大于10000的票
                double amount = Double.valueOf(meterOrder.getPayAmount());
                int times = (int)(amount/maxMoney);
                for (int i = 0; i < times; i++){
                    invoiceReqDetail.setMoney(maxMoney);
                    feignChargeService.openBlue(JSON.toJSONString(invoiceReqDetail), invoiceReqDetail.getTenantId());
                    Thread.sleep(500);
                }
                invoiceReqDetail.setMoney(amount - times*maxMoney);
                feignChargeService.openBlue(JSON.toJSONString(invoiceReqDetail), invoiceReqDetail.getTenantId());
                return Result.ok("开票成功！");
            } catch (Exception ex) {
                log.info("开票失败，订单号====", meterOrder.getSn());
                return Result.error("开票异常！");
            }
        }
        return Result.error("选择非电子发票");
    }

    @Override
    public String getOpenId(String cn) {
        return meterOrderMapper.getOpenId(cn);
    }

    /**
     * 仪表线下充值
     * @param meterOrder
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<MeterOrder> unLineCharge(MeterOrder meterOrder) {
        Result<MeterOrder> result = new Result<MeterOrder>();
        if (StringUtils.isBlank(meterOrder.getPayAmount())) throw new RuntimeException("充值金额不能为空");
        //1.生成充值缴费单、费用明细记录、充值到表
        try {
            Date payDate = new Date();
            Meter meter = meterService.getSelfById( meterOrder.getMeterId());
            if (meter == null){
                return Result.error("系统中未查到需要充值的表号！");
            }
            meterOrder.setTenantId(meter.getTenantId());
            meterOrder.setProjectId(meter.getProjectId());
            meterOrder.setId(UUID.randomUUID().toString().replace("-", ""));
            String sn = StringUtils.createSn(meter.getProjectCode(), 3);
            meterOrder.setSn(sn);
            meterOrder.setPayStatus(PayStatusEnum.PAY_STATUS_YES.getCode());
            meterOrder.setPayMode(PayModeEnum.PAY_MODE_OFFLINE.getCode());
            meterOrder.setPayTime(payDate);
            meterOrder.setCreateBy(SsoUtil.getLoginUser().getId());
            meterOrder.setCreateTime(new Date());
//            //计算每个子表的充值金额
//            List<MeterPaymentDetailReqVo> detailReqVoList = reqVo.getPaymentDetailReqVoList();
//            for (MeterPaymentDetailReqVo detailReqVo : detailReqVoList) {
            //构造充值明细记录
            MeterFeeRule meterFeeRule = meterFeeRuleService.queryFeeByMeterId(meter.getId());
            Integer roundMode = meterFeeRule.getRoundMode();
            MeterChargeInfo meterCharge = new MeterChargeInfo();
            meterCharge.setTenantId(meter.getTenantId());
            meterCharge.setId(UUID.randomUUID().toString().replace("-", ""));
            meterCharge.setChargeAmount(meterOrder.getPayAmount());
            meterCharge.setChargeType(MeterChargeTypeEnum.METER_CHARGE_TYPE_PAY.getCode());
            meterCharge.setChargeTime(payDate);
            meterCharge.setMeterId(meterOrder.getMeterId());
            meterCharge.setChargeStatus(MeterChargeStatusEnum.METER_CHARGE_STATUS_ING.getCode());
            meterCharge.setMeterOrderId(meterOrder.getId());
            meterCharge.setRound(roundMode);
            List<MeterOrderInvoice> meterOrderInvoiceList = getMeterOrderInvoiceList(meterOrder, meter, meterCharge);
            meterOrderMapper.insert(meterOrder);
            meterChargeInfoService.save(meterCharge);
            List<MeterChargeRespVo> meterChargeList = Lists.newArrayList(); //费用明细表集合
            MeterChargeRespVo meterChargeRespVo = new MeterChargeRespVo();
            BeanUtils.copyProperties(meterCharge,meterChargeRespVo);
            meterChargeList.add(meterChargeRespVo);
            if (meterOrderInvoiceList.size() > 0) {
                meterOrderInvoiceMapper.batchInsert(meterOrderInvoiceList);
            }
            List<MeterSwitchRespVo> switchRespVoList = meterChargeInfoService.refreshRemainByPay(meterChargeList, meterOrder.getId(), MeterChargeTypeEnum.METER_CHARGE_TYPE_PAY.getCode());
            meterOrder.setSwitchRespVoList(switchRespVoList);

        }catch (RuntimeException re){
            log.error("MeterOrderServiceImpl unLineCharge 异常",re);
            throw new RuntimeException(re.getMessage());
        } catch (Exception e){
            log.error("MeterOrderServiceImpl unLineCharge 异常",e);
            throw new RuntimeException("充值处理异常,充值失败",e);
        }
        return Result.ok(meterOrder);
    }

    @Override
    public Result<Object> unLineQRCodeCharge(MeterOrder meterOrder) {
        //根据项目ID获取到对应的支付配置
        MeterRoom meterRoom = meterRoomMapper.selectByMeterId(meterOrder.getMeterId());
        if (null == meterRoom){
            return Result.error("电表未绑定房间！");
        }
        MeterPayConfig payConfig = meterOrderMapper.getMeterPayConfig(meterOrder.getProjectId(), "scanner");
        PayAccountConfig accountConfig = meterOrderMapper.getPayConfigByFid(meterRoom.getBuildingId(),"5e6f302de10255c7a6424055ddea7acc", "scanner");
        if (null == accountConfig){
            if (null == payConfig){
                return Result.error("无支付配置");
            }
        }else {
            String notifyUrl = payConfig.getNotifyUrl();
            BeanUtils.copyProperties(accountConfig, payConfig);
            payConfig.setNotifyUrl(notifyUrl);
        }

        String sn = StringUtils.createSn(payConfig.getProjectCode(), 3);
        meterOrder.setSn(sn);
        meterOrder.setPayChannel(payConfig.getChannel());
        if ("FFT".equals(payConfig.getChannel())){
            String payResCode = "-1";
            String request = "";
            JSONObject payRes = null;

            //调用银行接口
            List<Object> list = new ArrayList<Object>();
            FFTFeeItem feeMoney = new FFTFeeItem();
            feeMoney.setSubjectName("水电费");
            feeMoney.setDetailAmt(meterOrder.getPayAmount().toString());
            list.add(feeMoney);
            FFTCreateOrder fftCreateOrder = new FFTCreateOrder();
            fftCreateOrder.setReqNo(sn);
            fftCreateOrder.setOrgNo(payConfig.getOrgNo());
            fftCreateOrder.setVillageName(payConfig.getProjectName());
            String preStr = meterOrder.getPayQRCode().substring(0, 2);
            if (preStr.equals("28")){ // 支付宝二维码
                meterOrder.setPayType(PayTypeEnum.PAY_METHOD_ALIPAY.getCode().toString());
                fftCreateOrder.setPaymentType("03");
            }else {
                meterOrder.setPayType(PayTypeEnum.PAY_METHOD_WEIXINPAY.getCode().toString());
                fftCreateOrder.setPaymentType("04");
            }
            fftCreateOrder.setPaymentModel("00");
            fftCreateOrder.setOrderAmt(new BigDecimal(meterOrder.getPayAmount()));
            fftCreateOrder.setNotifyUrl(payConfig.getNotifyUrl());
            fftCreateOrder.setOriOrderDetails(list);
            fftCreateOrder.setAddress(payConfig.getAddress());
            fftCreateOrder.setCity(payConfig.getCity());
            fftCreateOrder.setProvince(payConfig.getProvince());
            fftCreateOrder.setCounty(payConfig.getCounty());
            request = JSONObject.toJSONString(fftCreateOrder);
            log.info("水电加密参数===="+request);
            String cipher = Sm4Util.encryptEcb(fftEncryptKey, request);
            try {
                payRes = ComUtil.doPost(payConfig.getPayUrl()+"/ori/createOrder",cipher,fftEncryptKey);
                log.info("水电返回json========="+ payRes);
                payResCode = payRes.getString("returnCode");
            }catch (Exception e){
                log.error("水电缴费调用下单接口异常:{}",e);
                return Result.error("水电缴费调用银行支付接口繁忙！");
            }
            meterOrder.setRequest(request);
            if ("0000".equals(payResCode)){
                String  data = payRes.getString("data");
                JSONObject jsonObject = JSONObject.parseObject(data);
                String transNo = jsonObject.getString("transNo");
                meterOrder.setResponse(JSONObject.toJSONString(jsonObject));
                meterOrder.setPayMode(PayModeEnum.PAY_MODE_SCANNER.getCode());
                meterOrder.setId(UUID.randomUUID().toString().replace("-",""));
                meterOrder.setCreateTime(new Date());
                meterOrder.setTransNo(transNo);
                meterOrderMapper.insert(meterOrder);
                Map<String, String> param = new HashMap<>();
                param.put("payUserCode", meterOrder.getPayQRCode());
                param.put("transNo", transNo);
                String paramStr = JSONObject.toJSONString(param);
                String jsonmin = Sm4Util.encryptEcb(fftEncryptKey, paramStr);
                String url = payConfig.getPayUrl() +"/ori/payOrder";
                try {
                    JSONObject res = ComUtil.doPost(url, jsonmin, fftEncryptKey);
                    log.info("水电付费通ori/payOrder请求结果=========" + res);
                    String code = res.getString("returnCode");
                    String msg = res.getString("returnMsg");
                    if ("0000".equals(code)){
                        String queryData = "00";
                        final long timeInterval = 5000;
                        int i = 1;
                        Map<String, String> qParam = new HashMap<>();
                        qParam.put("transNo", transNo);
                        String qParamStr = JSONObject.toJSONString(qParam);
                        String qJsonMin = Sm4Util.encryptEcb(fftEncryptKey, qParamStr);
                        String queryUrl = payConfig.getPayUrl() +"/ori/queryPayResult";
                        while (i <= 20){
                            try {
                                JSONObject queryRes = ComUtil.doPost(queryUrl, qJsonMin, fftEncryptKey);
                                log.info("水电付费通ori/queryPayResult订单{}查询结果:{}",transNo,queryRes);
                                queryData = queryRes.getString("data");
                                if ("02".equals(queryData)){
                                    FFTPayNotify stu = new FFTPayNotify();
                                    stu.setTransNo(transNo);
                                    stu.setOrderId(meterOrder.getSn());
                                    stu.setPaymentAmt(meterOrder.getPayAmount().toString());
                                    stu.setPaymentTime(DateUtils.date2Str(new Date(),DateUtils.yyyymmddhhmmss));

                                    Result<MeterOrder> mo = meterPayNotify(stu);
                                    // 开电票
                                    this.meterBlueInvoice(mo.getResult());
                                    // 执行通断
                                    if (mo.isSuccess()){
                                        meterControlSwitchService.controlSwitchMeter(mo.getResult().getSwitchRespVoList());
                                    }

                                    break;
                                }else if ("03".equals(queryRes)){
                                    log.info("水电表支付查询状态为支付失败,订单号:{}",transNo);
                                    break;
                                }else {
                                    Thread.sleep(timeInterval);
                                }
                            }catch (Exception ex){
                                log.error("水电表支付状态查询异常:执行次数:{},订单号:{}",ex,i,transNo);
                                return Result.error("水电支付接口请求失败");
                            }finally {
                                i++;
                            }
                        }
                        return Result.ok("支付成功");
                    }else {
                        return Result.error(msg);
                    }
                }catch (Exception ex){
                    log.info("水电支付接口请求失败", ex);
                    return Result.error("水电支付接口请求失败");
                }
            }else {
                return Result.error("水电银行下单失败");
            }
        }else {
            return Result.error("水电不支持的银行渠道");
        }
    }

    @Override
    public Result<Object> checkOrderByTransNo(String projectId, String transNo) {
        //根据项目ID获取到对应的支付配置
        MeterPayConfig payConfig = meterOrderMapper.getMeterPayConfig(projectId, "scanner");
        Map<String, String> param = new HashMap<>();
        param.put("transNo", transNo);
        String paramStr = JSONObject.toJSONString(param);
        String jsonmin = Sm4Util.encryptEcb(fftEncryptKey, paramStr);
        String url = payConfig.getPayUrl() +"/ori/queryPayResult";
        try {
            JSONObject res = ComUtil.doPost(url, jsonmin, fftEncryptKey);
            log.info("仪表付费通ori/queryPayResult订单{}查询结果{}",transNo,res);
            String code = res.getString("returnCode");
            String msg = res.getString("returnMsg");
            if ("0000".equals(code)){
                return Result.ok(res);
            }else {
                return Result.error(msg);
            }
        }catch (Exception ex){
            log.info("支付接口请求失败", ex);
            return Result.error("支付接口请求失败");
        }
    }

    private List<MeterOrderInvoice> getMeterOrderInvoiceList(MeterOrder meterOrder, Meter meter, MeterChargeInfo meterCharge) {
        //查找对应的收费项
        List<MeterFeeRule> meterFeeRuleList = meterFeeRuleMapper.findByMeterId(meterOrder.getMeterId());
        BigDecimal totalPrice = BigDecimal.ZERO;//总单价
        int precision = 0; //计算精度
        for (MeterFeeRule meterFeeRule : meterFeeRuleList) {
            BigDecimal price = meterFeeRule.getFeePrice();//单价
            totalPrice = totalPrice.add(price);
            if (meterFeeRule.getFeePrecision() != null && meterFeeRule.getFeePrecision() > precision) {
                precision = meterFeeRule.getFeePrecision();
            }
        }
        if (totalPrice.compareTo(BigDecimal.ZERO) == 0) {
            throw new RuntimeException("表" + meter.getMeterCode() + "收费项未配置或收费项已过期或收费项未启用");
        }
        meterCharge.setPrecision(precision);

        List<MeterOrderInvoice> meterOrderInvoiceList = Lists.newArrayList(); //税额明细表集合
        BigDecimal tmpAmount = BigDecimal.ZERO; //已计算的金额
        BigDecimal amount = meterCharge.getChargeAmount() == null ? BigDecimal.ZERO : new BigDecimal(meterCharge.getChargeAmount()); //单表充值总金额
        BigDecimal chargeUse = amount.divide(totalPrice,precision,BigDecimal.ROUND_HALF_UP);
        meterCharge.setChargeUse(chargeUse.toString());
        for (int i = 0; i < meterFeeRuleList.size(); i++) {
            MeterOrderInvoice orderInvoice = new MeterOrderInvoice();
            MeterFeeRule feeRule = meterFeeRuleList.get(i); //收费项信息
            BigDecimal feePrice = feeRule.getFeePrice();
            BigDecimal feeAmount = BigDecimal.ZERO; //收费项金额
            if (i != meterFeeRuleList.size() - 1) {  //不是最后一条
                feeAmount = amount.multiply(feePrice.divide(totalPrice, precision, feeRule.getRoundMode()));
                tmpAmount = tmpAmount.add(feeAmount);
            } else {  //最后一条
                feeAmount = amount.subtract(tmpAmount);
            }
            BigDecimal feeRate = feeRule.getRate() == null ? BigDecimal.ZERO : new BigDecimal(feeRule.getRate()).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);
            BigDecimal rate = feeRate.add(BigDecimal.ONE);
            //计算收入   金额/(1 + 税率)
            BigDecimal  earning = feeAmount.divide(rate, 2, BigDecimal.ROUND_HALF_UP); //固定2位
            BigDecimal taxAmount = feeAmount.subtract(earning); //税额
            //记录税额信息
            orderInvoice.setPrice(feePrice.toString());
            orderInvoice.setId(UUID.randomUUID().toString().replace("-", ""));
            orderInvoice.setMeterOrderId(meterOrder.getId());//订单表id
            orderInvoice.setChargeInfoId(meterCharge.getId());//费用明细表id
            orderInvoice.setFeeRuleId(feeRule.getId());//收费项ID
//            SimpleDateFormat sdf =new SimpleDateFormat("yyyy-MM");
////            String time = sdf.format(meterOrder.getPayTime());
////            orderInvoice.setContent(time+feeRule.getFeeName());
            Integer invoiceClassId = feeRule.getInvoiceClass();
            if (invoiceClassId != null && invoiceClassId > 0) {
//                    FeeGuoxinInvoiceClass guoxinInvoiceClass = invoiceClassService.getById(invoiceClassId.longValue());
//                    if (guoxinInvoiceClass != null) {
//                        orderInvoice.setInvoiceCode(guoxinInvoiceClass.getCode());
//                    }
            }
            orderInvoice.setFeeName(feeRule.getFeeName());//收费项名称
            orderInvoice.setFeeRate(feeRule.getRate());//税率
            orderInvoice.setTotalAmount(feeAmount.toString());//实收
            orderInvoice.setEarning(earning.toString());//收入
            orderInvoice.setTaxAmount(taxAmount.toString());//税额
            orderInvoice.setTenantId(meterOrder.getTenantId());
            orderInvoice.setRemark(feeRule.getRemarks());
            meterOrderInvoiceList.add(orderInvoice);
        }
        return meterOrderInvoiceList;
    }

    @Override
    public List<MeterOrder> findPage(Page<MeterOrder> page, MeterOrder meterOrder) {
        meterOrder.setTenantId(SsoUtil.getLoginUser().getTenantId());
        return meterOrderMapper.findPage(page, meterOrder);
    }

    @Override
    public Result<MeterOrder> getEvidence(String orderId) {
        Result<MeterOrder> result = new Result();
        try {
            if (StringUtils.isBlank(orderId)){
                return result.error500("查询参数不能为空");
            }
            MeterOrder meterOrder = meterOrderMapper.getById(orderId);
            if (meterOrder == null){
                return result.error500("为查询到当前订单信息");
            }
            //将支付金额转换为大写
            Rmb r = new Rmb(Double.valueOf(meterOrder.getPayAmount()));
            meterOrder.setPayAmount(r.toHanStr());
            meterOrder.setOrderInvoiceList(meterOrderInvoiceMapper.getBychargeInfo(meterOrder.getId()));
            result.setResult(meterOrder);
        }catch (Exception e){
            log.error("操作失败",e.getMessage());
            return Result.error("操作失败!");
        }
        return result;
    }

    @Override
    public List<ChargeInvoiceRequest> invoiceRequestListBySn(String orderNum) {
        return meterOrderMapper.invoiceRequestListBySn(orderNum);
    }

    @Override
    public ChargeInvoiceRequest invoiceRequestByFpqqlsh(String fpqqlsh) {
        return meterOrderMapper.invoiceRequestByFpqqlsh(fpqqlsh);
    }


}
